package com.matt.controller.web;

import com.dotflat.check.service.CCheckerService;
import com.matt.commons.dto.sso.AreaDTO;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.commons.model.StatusResponse;
import com.matt.commons.page.PagerQuery;
import com.matt.domain.*;
import com.matt.domain.mp.ParentUser;
import com.matt.domain.rel.RelClassesChildren;
import com.matt.domain.rel.RelClassesTeacher;
import com.matt.domain.vo.ChildrenMemorandumVo;
import com.matt.foundation.DO.ChildrenListDO;
import com.matt.foundation.DO.ChildrenNurseryListDO;
import com.matt.foundation.ext.aliyun.OSSProcessService;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.model.MemVerificationCache;
import com.matt.foundation.query.ChildrenNurseryQuery;
import com.matt.foundation.query.ChildrenQuery;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.utils.PoiUtils;
import com.matt.foundation.vo.AppUserDetailVo;
import com.matt.foundation.vo.ChildrenListVo;
import com.matt.foundation.vo.children.WebChildrenVo;
import com.matt.repository.ChildrenLeaveRequestRepository;
import com.matt.repository.ChildrenRepository;
import com.matt.repository.rel.RelClassesChildrenRepository;
import com.matt.repository.rel.RelClassesTeacherRepository;
import com.matt.service.*;
import com.matt.service.remoteCall.DTO.RoleDTO;
import com.matt.service.remoteCall.SsoCallService;
import com.tuo51.components.redis.RedisService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.EntityNotFoundException;
import javax.persistence.Table;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.AccessDeniedException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.foundation.constant.RequestConstant.TICKET;

;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2017/7/11
 * *******************************
 */
@RestController
@Slf4j
@RequestMapping("/web/children")
public class WebChildrenController {

    @Autowired
    private ChildrenService childrenService;

    @Autowired
    private ChildrenRepository childrenRepository;
    @Autowired
    private RelClassesChildrenRepository relClassesChildrenRepository;


    @Autowired
    private ClassesService classesService;

    @Autowired
    private RelChildrenMemorandumService relChildrenMemorandumService;

    @Autowired
    private ChildrenMemorandumService childrenMemorandumService;

    @Autowired
    private ChildrenLeaveRequestService childrenLeaveRequestService;

    @Autowired
    private ChildrenLeaveRequestRepository childrenLeaveRequestRepository;

    @Autowired
    private ChildrenVaccineService childrenVaccineService;


    @Autowired
    private VaccineNotificationsService vaccineNotificationsService;


    @Autowired
    private MemVerificationCache cache;

    @Autowired
    private CCheckerService cCheckerService;

    @Autowired
    AttaService attaService;

    @Autowired
    SsoCallService ssoCallService;
    @Autowired
    private RedisService redisService;

    @Autowired
    private OSSProcessService ossProcessService;

    @Value("${aliyun.oss.fileServerPrefix}")
    private String IMG_SERVICE_PREFIX;
    @Autowired
    private RelClassesTeacherService relClassesTeacherService;

//    /**
//     * 获取 RSA 公钥（前端调用）
//     */
//    @GetMapping("/getPublicKey")
//    public StatusResponse getPublicKey(String mobile) {
//        try {
//            // 生成 RSA 密钥对
//            KeyPair keyPair = RsaUtils.generateKeyPair();
//            PublicKey publicKey = keyPair.getPublic();
//            PrivateKey privateKey = keyPair.getPrivate();
//
//            // 将私钥 Base64 编码并存入 Redis，设置 5 分钟 TTL
//            String privateKeyBase64 = Base64.getEncoder().encodeToString(privateKey.getEncoded());
//            String redisKey = "rsa:private:" + mobile;
//            redisService.set(redisKey, privateKeyBase64, 5 * 60, TimeUnit.SECONDS);
//
//            // 返回公钥 Base64 编码
//            String publicKeyBase64 = Base64.getEncoder().encodeToString(publicKey.getEncoded());
//            return StatusResponse.success(publicKeyBase64);
//        } catch (Exception e) {
//            log.error("生成 RSA 密钥对失败", e);
//            return StatusResponse.error("000009","获取公钥失败");
//        }
//    }

    /**
     * 新增宝宝数据+备忘录数据
     */
    @PostMapping("/saveChildrenMemorandum")
    public StatusResponse saveChildrenMemorandum(@RequestBody ChildrenMemorandumVo childrenMemorandumVo){

        RelChildrenMemorandum relChildrenMemorandum =new RelChildrenMemorandum();
        relChildrenMemorandum.setClassesId(childrenMemorandumVo.getClassesId()); //班级id
        relChildrenMemorandum.setChldrenId(childrenMemorandumVo.getChldrenId()); //宝宝id
        relChildrenMemorandum.setName(childrenMemorandumVo.getName()); //宝宝姓名
        relChildrenMemorandum.setCreateTime(new Date()); //创建时间
        relChildrenMemorandum.setCreateUserId(childrenMemorandumVo.getCreateUserId()); //用户id
        relChildrenMemorandum.setCreateUserName(childrenMemorandumVo.getCreateUserName()); //用户名
        relChildrenMemorandumService.addRelChildrenMemorandum(relChildrenMemorandum);


        ChildrenMemorandum childrenMemorandum =new ChildrenMemorandum();
        childrenMemorandum.setRelChildrenMemorandumId(relChildrenMemorandum.getId()); //备忘录中间表id
        childrenMemorandum.setContent(childrenMemorandumVo.getContent()); //内容
        childrenMemorandum.setFile(childrenMemorandumVo.getFile()); //附件
        childrenMemorandum.setCreateTime(new Date()); //创建时间
        childrenMemorandum.setCreateUserId(childrenMemorandumVo.getCreateUserId()); //用户id
        childrenMemorandum.setCreateUserName(childrenMemorandumVo.getCreateUserName()); //用户名
        childrenMemorandumService.addChildrenMemorandum(childrenMemorandum);


        return StatusResponse.success();
    }



    /**
     * 新增备忘录数据
     */
    @PostMapping("/saveMemorandum")
    public StatusResponse saveMemorandum(@RequestBody ChildrenMemorandumVo childrenMemorandumVo){

        ChildrenMemorandum childrenMemorandum =new ChildrenMemorandum();
        childrenMemorandum.setRelChildrenMemorandumId(childrenMemorandumVo.getRelChildrenMemorandumId()); //备忘录中间表id
        childrenMemorandum.setContent(childrenMemorandumVo.getContent()); //内容
        childrenMemorandum.setFile(childrenMemorandumVo.getFile()); //附件
        childrenMemorandum.setCreateUserId(childrenMemorandumVo.getCreateUserId());
        childrenMemorandum.setCreateUserName(childrenMemorandumVo.getCreateUserName());
        childrenMemorandum.setCreateTime(new Date()); //


        childrenMemorandumService.addChildrenMemorandum(childrenMemorandum);

        return StatusResponse.success();
    }



    /**
     * 修改备忘录数据
     */
    @PostMapping("/editMemorandum")
    public StatusResponse editMemorandum(ChildrenMemorandumVo childrenMemorandumVo){
        ChildrenMemorandum childrenMemorandum = childrenMemorandumService.selChildrenMemorandumById(childrenMemorandumVo.getId());
        childrenMemorandum.setContent(childrenMemorandumVo.getContent()); //内容
        childrenMemorandum.setFile(childrenMemorandumVo.getFile()); //附件
        childrenMemorandumService.addChildrenMemorandum(childrenMemorandum);
        return StatusResponse.success();
    }



    /**
     * 删除备忘录数据
     */
    @PostMapping("/delMemorandum")
    public StatusResponse delMemorandum(ChildrenMemorandumVo childrenMemorandumVo){
        childrenMemorandumService.delChildrenMemorandum(childrenMemorandumVo.getId());
        return StatusResponse.success();
    }


    /**
     * 删除宝宝 + 备忘录数据
     */
    @PostMapping("/delChildrenMemorandum")
    public StatusResponse delChildrenMemorandum(String id){
        //先删除备忘录数据，再删除中间表数据。

        List<ChildrenMemorandum> childrenMemorandums = childrenMemorandumService.selChildrenMemorandumList(id);
        childrenMemorandumService.delChildrenMemorandumByList(childrenMemorandums);

        relChildrenMemorandumService.delRelChildrenMemorandum(id);
        return StatusResponse.success();
    }




    /**
     * 宝宝备忘录列表查询  + 详情查询
     */
    @GetMapping("/selChildrenMemorandumPage")
    public StatusResponse selChildrenMemorandumPage(String id,String classesId,String name,Integer pageNum,Integer pageSize){

        if (pageNum == null){
            pageNum = 0;
        }

        if (pageSize == null){
            pageSize = 10;
        }

        Page<RelChildrenMemorandum> page = relChildrenMemorandumService.findRelChildrenMemorandumPage(id,classesId,name,pageNum,pageSize);
        return StatusResponse.success(page);
    }
















    /**
     * 新增宝宝请假信息
     */
    @PostMapping("/saveChildrenLeaveRequest")
    @Transactional(rollbackFor = Exception.class)
    public StatusResponse saveChildrenLeaveRequest(@RequestBody ChildrenLeaveRequest childrenLeaveRequest){
        // 1. 基础参数校验（startTime和endTime不能为空）
        Date newStart = childrenLeaveRequest.getStartTime();
        Date newEnd = childrenLeaveRequest.getEndTime();
        String chldrenId = childrenLeaveRequest.getChldrenId();

        if (chldrenId == null || chldrenId.trim().isEmpty()) {
            throw new RuntimeException("宝宝ID不能为空");
        }
        if (newStart == null || newEnd == null) {
            throw new RuntimeException("请假开始时间和结束时间不能为空");
        }
        if (newStart.after(newEnd)) {
            throw new RuntimeException("请假开始时间不能晚于结束时间");
        }

        // 2. 核心：查询该宝宝是否有重叠的请假记录
        List<ChildrenLeaveRequest> overlappingLeaves = childrenLeaveRequestRepository
                .findOverlappingLeaveByChldrenId(chldrenId, newStart, newEnd);

        // 3. 存在重叠请假，直接提示
        if (!overlappingLeaves.isEmpty()) {
            log.warn("宝宝[{}]存在重叠请假记录，新请假时间：{} - {}，重叠记录数：{}",
                    chldrenId, newStart, newEnd, overlappingLeaves.size());
            throw new RuntimeException("该宝宝在当前时间段内已请假，无法重复提交");
        }

        // 4. 无重叠，继续原有业务逻辑
        childrenLeaveRequest.setCreateTime(new Date());
        if (StringUtils.isNotEmpty(childrenLeaveRequest.getState())) { // 请假状态为确认
            cCheckerService.checkinChildren1(chldrenId, newStart, 4, childrenLeaveRequest.getType() == 0 ? 1 : 0);
        } else {
            childrenLeaveRequest.setState("0"); // 默认未确认
        }

        childrenLeaveRequestService.addChildrenLeaveRequest(childrenLeaveRequest);
        // 3. 计算请假总天数（含开始和结束当天）
        int leaveDays = calculateLeaveDays(newStart, newEnd);
        Children children = childrenRepository.findById(chldrenId).get();

        // 处理null值：默认剩余天数为0
        Integer lastTuoNum = children.getLastTuoNum() != null ? children.getLastTuoNum() : 0;
        Integer tuoRemainingNum = children.getTuoRemainingNum() != null ? children.getTuoRemainingNum() : 0;
        int totalRemaining = lastTuoNum + tuoRemainingNum; // 总剩余天数

        if (leaveDays > 0) { // 确保有需要扣除的天数
            if (leaveDays >= totalRemaining) {
                // 扣除天数 >= 总剩余天数：全部清零
                children.setLastTuoNum(0);
                children.setTuoRemainingNum(0);
                log.info("宝宝[{}]托育天数不足（总剩余{}天），扣除后全部清零", chldrenId, totalRemaining);
            } else {
                // 优先扣上一个包的剩余天数
                if (lastTuoNum >= leaveDays) {
                    children.setLastTuoNum(lastTuoNum - leaveDays);
                    log.info("宝宝[{}]从上个包扣除{}天，剩余上个包天数：{}",
                            chldrenId, leaveDays, lastTuoNum - leaveDays);
                } else {
                    // 上个包扣完后，剩余部分扣当前包
                    int remainingNeedDeduct = leaveDays - lastTuoNum;
                    children.setLastTuoNum(0); // 上个包清零
                    children.setTuoRemainingNum(tuoRemainingNum - remainingNeedDeduct);
                    log.info("宝宝[{}]上个包扣完（{}天），从当前包扣除{}天，剩余当前包天数：{}",
                            chldrenId, lastTuoNum, remainingNeedDeduct, tuoRemainingNum - remainingNeedDeduct);
                }
            }
            childrenRepository.save(children); // 保存更新
        }
        return StatusResponse.success();
    }

    /**
     * 计算请假总天数（含开始和结束日期当天）
     * 例：2025-10-01 14:00 至 2025-10-03 10:00 → 3天（1号、2号、3号）
     */
    private int calculateLeaveDays(Date start, Date end) {
        // 截断时间部分，只保留日期（避免时间差影响天数计算）
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(start);
        startCal.set(Calendar.HOUR_OF_DAY, 0);
        startCal.set(Calendar.MINUTE, 0);
        startCal.set(Calendar.SECOND, 0);
        startCal.set(Calendar.MILLISECOND, 0);

        Calendar endCal = Calendar.getInstance();
        endCal.setTime(end);
        endCal.set(Calendar.HOUR_OF_DAY, 0);
        endCal.set(Calendar.MINUTE, 0);
        endCal.set(Calendar.SECOND, 0);
        endCal.set(Calendar.MILLISECOND, 0);

        // 计算天数差（结束日期 - 开始日期 + 1，确保首尾都算）
        long startMillis = startCal.getTimeInMillis();
        long endMillis = endCal.getTimeInMillis();
        long dayMillis = 24 * 60 * 60 * 1000L; // 一天的毫秒数
        int days = (int) ((endMillis - startMillis) / dayMillis) + 1;

        return Math.max(days, 1); // 至少1天（避免0天的异常情况）
    }


//    /**
//     * 修改宝宝请假信息
//     */
//    @PostMapping("/editChildrenLeaveRequest")
//    public StatusResponse editChildrenLeaveRequest(@RequestBody ChildrenLeaveRequest childrenLeaveRequest){
//        ChildrenLeaveRequest childrenLeave = childrenLeaveRequestService.getChildrenLeaveRequestById(childrenLeaveRequest.getId());
//
////        childrenLeave.setLeaveContent(childrenLeaveRequest.getLeaveContent()); //请假内容
////        childrenLeave.setStartTime(childrenLeaveRequest.getStartTime()); //开始时间
////        childrenLeave.setEndTime(childrenLeaveRequest.getEndTime()); //结束时间
////        childrenLeave.setState(childrenLeaveRequest.getState()); //宝宝状态
////        childrenLeave.setType(childrenLeaveRequest.getType()); //请假类型
////        childrenLeave.setCourseProductId(childrenLeaveRequest.getCourseProductId());//请假关联课程id
////        childrenLeave.setCourseProductName(childrenLeaveRequest.getCourseProductName()); //请假关联课程名称
////        childrenLeave.setState(childrenLeaveRequest.getState());//状态
//
//        try {
//            BeanUtils.copyProperties(childrenLeave,childrenLeaveRequest);
//        } catch (IllegalAccessException e) {
//
//        } catch (InvocationTargetException e) {
//            throw new RuntimeException(e);
//        }
//
//        childrenLeaveRequestService.addChildrenLeaveRequest(childrenLeave);
//        return StatusResponse.success();
//    }






    @PostMapping("/editChildrenLeaveRequest")
    public StatusResponse editChildrenLeaveRequest(@RequestBody ChildrenLeaveRequest childrenLeaveRequest) {
        // 1. 先校验请求核心参数（id必须传，否则无法查询原始记录）
        if (childrenLeaveRequest.getId() == null || childrenLeaveRequest.getId().trim().isEmpty()) {
            throw new RuntimeException("请假记录ID不能为空");
        }

        // 2. 查询原始记录（必须在拷贝参数前，确保能拿到旧数据）
        ChildrenLeaveRequest childrenLeave = childrenLeaveRequestService.getChildrenLeaveRequestById(childrenLeaveRequest.getId());
        if (childrenLeave == null) {
            throw new RuntimeException("编辑的请假记录不存在");
        }

        // 3. 提取原始旧数据（用于还原旧天数，关键：拷贝前保存旧值）
        String originalChldrenId = childrenLeave.getChldrenId(); // 原始宝宝ID（必存在）
        Date originalOldStart = childrenLeave.getStartTime(); // 编辑前的旧开始时间
        Date originalOldEnd = childrenLeave.getEndTime(); // 编辑前的旧结束时间

        // 4. 区分“前端未传chldrenId”和“传了chldrenId”，执行不同逻辑
        boolean isChldrenIdNotPassed = !Optional.ofNullable(childrenLeaveRequest.getChldrenId()).isPresent();
        String chldrenId = isChldrenIdNotPassed ? originalChldrenId : childrenLeaveRequest.getChldrenId();

        // 5. 基础参数校验（所有场景都需校验）
        Date newStart = childrenLeaveRequest.getStartTime() != null ? childrenLeaveRequest.getStartTime() : originalOldStart;
        Date newEnd = childrenLeaveRequest.getEndTime() != null ? childrenLeaveRequest.getEndTime() : originalOldEnd;
        String currentLeaveId = childrenLeave.getId(); // 排除自身重叠查询

        if (chldrenId == null || chldrenId.trim().isEmpty()) {
            throw new RuntimeException("宝宝ID不能为空");
        }
        if (newStart == null || newEnd == null) {
            throw new RuntimeException("请假开始时间和结束时间不能为空");
        }
        if (newStart.after(newEnd)) {
            throw new RuntimeException("请假开始时间不能晚于结束时间");
        }

        // 6. 重叠请假校验（所有场景都需校验，避免重复请假）
        List<ChildrenLeaveRequest> overlappingLeaves = childrenLeaveRequestRepository
                .findOverlappingLeaveByChldrenId1(chldrenId, newStart, newEnd, currentLeaveId);
        if (!overlappingLeaves.isEmpty()) {
            log.warn("宝宝[{}]存在其他重叠请假记录，新请假时间：{} - {}，重叠记录数：{}",
                    chldrenId, newStart, newEnd, overlappingLeaves.size());
            throw new RuntimeException("该宝宝在当前时间段内已存在其他请假记录，无法编辑");
        }

        // 7. 查询宝宝信息（用orElseThrow自定义异常，避免NoSuchElementException）
        Children children = childrenRepository.findById(chldrenId)
                .orElseThrow(() -> new RuntimeException("宝宝信息不存在"));

        // 8. 核心业务逻辑：分场景处理天数扣除/还原
        // 场景A：前端未传chldrenId（确认请假，需还原旧天数→扣新天数）
        if (isChldrenIdNotPassed) {
            // 8.1 还原旧请假天数（用拷贝前的原始旧时间）
            int oldLeaveDays = calculateLeaveDays(originalOldStart, originalOldEnd);
            log.info("宝宝[{}]原始请假天数：{}天（{}至{}），开始还原", chldrenId, oldLeaveDays, originalOldStart, originalOldEnd);

            Integer lastTuoNum = children.getLastTuoNum() != null ? children.getLastTuoNum() : 0;
            Integer tuoRemainingNum = children.getTuoRemainingNum() != null ? children.getTuoRemainingNum() : 0;

            if (oldLeaveDays > 0) {
                // 优先还原上一个包
                int restoreToLast = Math.min(oldLeaveDays, Integer.MAX_VALUE - lastTuoNum);
                children.setLastTuoNum(lastTuoNum + restoreToLast);
                oldLeaveDays -= restoreToLast;

                // 剩余还原到当前包
                if (oldLeaveDays > 0) {
                    children.setTuoRemainingNum(tuoRemainingNum + oldLeaveDays);
                }
                childrenRepository.save(children);
                log.info("宝宝[{}]还原后：上一个包剩余{}天，当前包剩余{}天",
                        chldrenId, children.getLastTuoNum(), children.getTuoRemainingNum());
            }

            // 8.2 扣除新请假天数（用新时间）
            int newLeaveDays = calculateLeaveDays(newStart, newEnd);
            log.info("宝宝[{}]新请假天数：{}天（{}至{}），开始扣除", chldrenId, newLeaveDays, newStart, newEnd);

            lastTuoNum = children.getLastTuoNum() != null ? children.getLastTuoNum() : 0;
            tuoRemainingNum = children.getTuoRemainingNum() != null ? children.getTuoRemainingNum() : 0;
            int totalRemaining = lastTuoNum + tuoRemainingNum;

            if (newLeaveDays > 0) {
                if (newLeaveDays >= totalRemaining) {
                    children.setLastTuoNum(0);
                    children.setTuoRemainingNum(0);
                    log.info("宝宝[{}]托育天数不足（总剩余{}天），扣除后全部清零", chldrenId, totalRemaining);
                } else {
                    if (lastTuoNum >= newLeaveDays) {
                        children.setLastTuoNum(lastTuoNum - newLeaveDays);
                        log.info("宝宝[{}]从上个包扣除{}天，剩余上个包天数：{}",
                                chldrenId, newLeaveDays, children.getLastTuoNum());
                    } else {
                        int remainingNeedDeduct = newLeaveDays - lastTuoNum;
                        children.setLastTuoNum(0);
                        children.setTuoRemainingNum(tuoRemainingNum - remainingNeedDeduct);
                        log.info("宝宝[{}]上个包扣完（{}天），从当前包扣除{}天，剩余当前包天数：{}",
                                chldrenId, lastTuoNum, remainingNeedDeduct, children.getTuoRemainingNum());
                    }
                }
                childrenRepository.save(children);
            }

            // 8.3 确认请假的额外处理（调用checkinChildren1）
            Integer type = childrenLeaveRequest.getType() == null ? 0 : childrenLeaveRequest.getType();
            cCheckerService.checkinChildren1(chldrenId, newStart, 4, type == 0 ? 1 : 0);

        } else {
            // 场景B：前端传了chldrenId（普通编辑，直接扣天数）
            int leaveDays = calculateLeaveDays(newStart, newEnd);
            log.info("宝宝[{}]编辑请假天数：{}天（{}至{}），开始扣除", chldrenId, leaveDays, newStart, newEnd);

            Integer lastTuoNum = children.getLastTuoNum() != null ? children.getLastTuoNum() : 0;
            Integer tuoRemainingNum = children.getTuoRemainingNum() != null ? children.getTuoRemainingNum() : 0;
            int totalRemaining = lastTuoNum + tuoRemainingNum;

            if (leaveDays > 0) {
                if (leaveDays >= totalRemaining) {
                    children.setLastTuoNum(0);
                    children.setTuoRemainingNum(0);
                    log.info("宝宝[{}]托育天数不足（总剩余{}天），扣除后全部清零", chldrenId, totalRemaining);
                } else {
                    if (lastTuoNum >= leaveDays) {
                        children.setLastTuoNum(lastTuoNum - leaveDays);
                        log.info("宝宝[{}]从上个包扣除{}天，剩余上个包天数：{}",
                                chldrenId, leaveDays, lastTuoNum - leaveDays);
                    } else {
                        int remainingNeedDeduct = leaveDays - lastTuoNum;
                        children.setLastTuoNum(0);
                        children.setTuoRemainingNum(tuoRemainingNum - remainingNeedDeduct);
                        log.info("宝宝[{}]上个包扣完（{}天），从当前包扣除{}天，剩余当前包天数：{}",
                                chldrenId, lastTuoNum, remainingNeedDeduct, tuoRemainingNum - remainingNeedDeduct);
                    }
                }
                childrenRepository.save(children);
            }

            // 普通编辑的额外处理（若有需要）
            Integer type = childrenLeaveRequest.getType() == null ? 0 : childrenLeaveRequest.getType();
            cCheckerService.checkinChildren1(chldrenId, newStart, 4, type == 0 ? 1 : 0);
        }

        // 9. 最后执行参数拷贝（校验和业务逻辑都通过后）
        BeanUtils.copyProperties(childrenLeaveRequest, childrenLeave, getNullPropertyNames(childrenLeaveRequest));
        // 10. 保存编辑后的请假记录
        childrenLeaveRequestService.addChildrenLeaveRequest(childrenLeave);

        log.info("宝宝[{}]请假记录编辑完成", chldrenId);
        return StatusResponse.success();
    }




    // 获取对象中为null的属性名数组
    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
        Set<String> emptyNames = new HashSet<>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }












    /**
     * 删除宝宝请假信息
     */
    @PostMapping("/delChildrenLeaveRequest")
    public StatusResponse delChildrenLeaveRequest(@RequestBody ChildrenLeaveRequest childrenLeaveRequest){
        childrenLeaveRequestService.delete(childrenLeaveRequest.getId());
        return StatusResponse.success();
    }





    /**
     * 敏感操作验证
     */
    @GetMapping("/adminSensitivity")
    public StatusResponse adminSensitivity(String code){
        if (code.equals("9999")){
            return StatusResponse.success(1);
        }else {
            return StatusResponse.success(0);
        }
    }





    /**
     * 宝宝请假信息列表查询
     */
    @GetMapping("/selChildrenLeaveRequestPage")
    public StatusResponse selChildrenLeaveRequestPage(String aid, @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime, String chldrenId, String classesId, String name, String leaveType,String type,Integer pageNum, Integer pageSize) {
//        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
//        if ("老师".equals(staffRole.getRoleName())) {
//            if (classesId == null||classesId.equals("")){
//                classesId="999";
//            }
//        }
        List<String> collect=new ArrayList<>();
        Page<ChildrenLeaveRequest> childrenLeaveRequests = childrenLeaveRequestService.selChildrenLeaveRequest(aid,startTime,chldrenId, classesId, name,leaveType, type,pageNum, pageSize, collect);

        List<ChildrenLeaveRequest> content = childrenLeaveRequests.getContent();
        for (int i=0;i<content.size();i++){
            ChildrenLeaveRequest childrenLeaveRequest = content.get(i);
            Classes classes = classesService.selectClassById(childrenLeaveRequest.getClassesId());
            if (classes !=null) {
                childrenLeaveRequest.setClassesName(classes.getName());
            }
        }

        return StatusResponse.success(childrenLeaveRequests);
    }


    @Autowired
    private RelClassesTeacherRepository relClassesTeacherRepository;
    /**
     * 宝宝请假信息列表查询
     */
    @GetMapping("/selChildrenLeaveRequestPage1")
    public StatusResponse selChildrenLeaveRequestPage1(@RequestHeader(TICKET) String ticket, String aid, @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime, String chldrenId, String classesId, String name, String leaveType,String type,Integer pageNum, Integer pageSize,Integer isShow){
        StaffDTO staffDTO = ssoCallService.getStaffDTO(ticket);
        List<String> collect = new ArrayList<>();
        List<RelClassesTeacher> byStaffId = relClassesTeacherRepository.findByStaffId(staffDTO.getId());
        if (!byStaffId.isEmpty()){
            collect = byStaffId.stream().map(RelClassesTeacher::getClassesId).collect(Collectors.toList());
        }

        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
        // 关键调整1：老师角色 - 前端传了classesId就用传的，未传则用collect（去掉错误的"999"赋值）
        if ("老师".equals(staffRole.getRoleName())||"班主任".equals(staffRole.getRoleName())) {
            // 前端未传classesId时，保持为空（后续查询用collect）；传了则直接使用
            if (classesId == null || classesId.trim().isEmpty()) {
                log.info("老师角色，前端未传classesId，使用所在班级集合查询：{}", collect);
            } else {
                log.info("老师角色，优先使用前端传的classesId查询：{}", classesId);
            }
        }
        // 园长角色 - 前端传了classesId就用传的，未传则不限制班级（或按其他条件）
        if ("园长".equals(staffRole.getRoleName())) {
            if (classesId != null && !classesId.trim().isEmpty()) {
                log.info("园长角色，优先使用前端传的classesId查询：{}", classesId);

            }else {
                collect=new ArrayList<>();
            }
        }

        // 调用查询服务（传入原始classesId和collect，由服务层处理优先级）
        Page<ChildrenLeaveRequest> childrenLeaveRequests = childrenLeaveRequestService.selChildrenLeaveRequest1(
                aid, startTime, chldrenId, classesId, name, leaveType, type, pageNum, pageSize, collect,isShow);

        // 补充班级名称
        List<ChildrenLeaveRequest> content = childrenLeaveRequests.getContent();
        for (ChildrenLeaveRequest request : content) {
            Classes classes = classesService.selectClassById(request.getClassesId());
            if (classes != null) {
                request.setClassesName(classes.getName());
            }
        }

        return StatusResponse.success(childrenLeaveRequests);
    }



//
//    /**
//     * 宝宝请假信息数据导出
//     */
//    @GetMapping("/selChildrenLeaveRequestExport")
//    public void selChildrenLeaveRequestExport(HttpServletResponse response,
//                                              String aid,
//                                              @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,
//                                              String chldrenId,
//                                              String classesId,
//                                              String name,
//                                              String leaveType,
//                                              String type) {
//
//        try {
//            // 获取所有数据（不分页），使用最大数量
//            Page<ChildrenLeaveRequest> childrenLeaveRequests = childrenLeaveRequestService.selChildrenLeaveRequest(
//                    aid, startTime, chldrenId, classesId, name, leaveType, type, 1, Integer.MAX_VALUE);
//
//            List<ChildrenLeaveRequest> content = childrenLeaveRequests.getContent();
//
//            // 处理班级名称（与列表查询保持一致）
//            for (int i = 0; i < content.size(); i++) {
//                ChildrenLeaveRequest childrenLeaveRequest = content.get(i);
//                Classes classes = classesService.selectClassById(childrenLeaveRequest.getClassesId());
//                if (classes != null) {
//                    childrenLeaveRequest.setClassesName(classes.getName());
//                }
//            }
//
//            // 封装需要导出的数据
//            List<ExcelDataVo> excelDataVoList = new ArrayList<>();
//
//            // 表头列名
//            List<String> headerNames = Arrays.asList(
//                    "班级", "开始时间", "结束时间", "请假内容", "宝宝姓名", "确认状态"
//            );
//
//            // 表头列对应的属性名
//            List<String> headerAttributes = Arrays.asList(
//                    "classesName", "startTime", "endTime", "leaveContent", "name", "state"
//            );
//
//            // 数据列表
//            List<Map<String, Object>> dataList = content.stream().map(item -> {
//                Map<String, Object> map = new HashMap<>();
//
//                // 使用处理后的classesName字段（与列表查询保持一致）
//                map.put("classesName", item.getClassesName() != null ? item.getClassesName() : "");
//                map.put("startTime", item.getStartTime());
//                map.put("endTime", item.getEndTime());
//                map.put("leaveContent", item.getLeaveContent() != null ? item.getLeaveContent() : "");
//                map.put("name", item.getName() != null ? item.getName() : "");
//
//                // 状态转换
//                String stateText = "";
//                if ("0".equals(item.getState())) {
//                    stateText = "未确认";
//                } else if ("1".equals(item.getState())) {
//                    stateText = "已确认";
//                } else if ("2".equals(item.getState())) {
//                    stateText = "已取消";
//                } else {
//                    stateText = "未知状态";
//                }
//                map.put("state", stateText);
//
//                return map;
//            }).collect(Collectors.toList());
//
//            // 封装 Excel 数据
//            ExcelDataVo excelDataVo = new ExcelDataVo();
//            excelDataVo.setSheetName("宝宝请假信息");
//            excelDataVo.setSheetTopColHeaderTitle("宝宝请假信息");
//            excelDataVo.setSheetTopColHeaderName(headerNames.toArray(new String[0]));
//            excelDataVo.setSheetTopColHeaderAttribute(headerAttributes.toArray(new String[0]));
//            excelDataVo.setSheetDataList(dataList);
//            excelDataVoList.add(excelDataVo);
//
//            // 设置响应头
//            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//            String fileName = "宝宝请假信息导出_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".xlsx";
//            String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
//            response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
//
//            // 导出 Excel 文件 - 直接写入response
//            new PackExcelSheetsDataUtil().packExcelSheetsData(response, "宝宝请假信息", excelDataVoList);
//
//        } catch (Exception e) {
//            log.error("导出异常!", e);
//            try {
//                response.setContentType("application/json");
//                response.setCharacterEncoding("UTF-8");
//                response.getWriter().write("{\"code\":500,\"msg\":\"导出失败\"}");
//            } catch (IOException ioException) {
//                log.error("写入错误响应失败", ioException);
//            }
//        }
//    }
//



//
//
//    @GetMapping("/selChildrenLeaveRequestExport")
//    public void selChildrenLeaveRequestExport(
//            HttpServletResponse response,
//            String aid,
//            @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,
//            @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime,
//            String chldrenId,
//            String classesId,
//            String name,
//            String leaveType,
//            String type) throws IOException {
//
//        // 获取所有数据（不分页）
//
//        Page<ChildrenLeaveRequest> childrenLeaveRequests = childrenLeaveRequestService.selChildrenLeaveRequest(aid,startTime,chldrenId, classesId, name,leaveType, type,1, 1000);
//
//        List<ChildrenLeaveRequest> content = childrenLeaveRequests.getContent();
//
//        // 设置响应头
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        String fileName = "宝宝请假信息导出.xlsx";
//        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
//        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);
//
//        // 使用SXSSFWorkbook支持大数据量
//        Workbook workbook = new SXSSFWorkbook(100);
//        Sheet sheet = workbook.createSheet("宝宝请假信息");
//
//        // 创建表头（带中文字体）
//        Row headerRow = sheet.createRow(0);
//        String[] headers = {"班级", "开始时间", "结束时间", "请假内容", "宝宝姓名", "确认状态"};
//
//        Font font = workbook.createFont();
//        font.setFontName("宋体");
//        CellStyle headerStyle = workbook.createCellStyle();
//        headerStyle.setFont(font);
//
//        for (int i = 0; i < headers.length; i++) {
//            Cell cell = headerRow.createCell(i);
//            cell.setCellValue(headers[i]);
//            cell.setCellStyle(headerStyle);
//        }
//
//        // 填充数据
//        int rowNum = 1;
//        for (ChildrenLeaveRequest item : content) {
//            Row row = sheet.createRow(rowNum++);
//
//            Classes classes = classesService.selectClassById(item.getClassesId());
//            row.createCell(0).setCellValue(classes != null ? classes.getName() : "");
//
//            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
//            row.createCell(1).setCellValue(item.getStartTime() != null ? sdf.format(item.getStartTime()) : "");
//            row.createCell(2).setCellValue(item.getEndTime() != null ? sdf.format(item.getEndTime()) : "");
//
//            row.createCell(3).setCellValue(item.getLeaveContent() != null ? item.getLeaveContent() : "");
//            row.createCell(4).setCellValue(item.getName() != null ? item.getName() : "");
//
//            String stateStr = "未知";
//            if ("0".equals(item.getState())) stateStr = "未确认";
//            else if ("1".equals(item.getState())) stateStr = "已确认";
//            else if ("2".equals(item.getState())) stateStr = "已取消";
//            row.createCell(5).setCellValue(stateStr);
//        }
//
//        // 自动调整列宽
//        for (int i = 0; i < headers.length; i++) {
//            sheet.autoSizeColumn(i);
//        }
//
//        // 写入响应流
//        workbook.write(response.getOutputStream());
//        workbook.close();
//
//        // 清理SXSSFWorkbook临时文件
//        if (workbook instanceof SXSSFWorkbook) {
//            ((SXSSFWorkbook) workbook).dispose();
//        }
//    }






    @GetMapping("/selChildrenLeaveRequestExport")
    public void selChildrenLeaveRequestExport(
            HttpServletResponse response,
            String aid,
            @DateTimeFormat(pattern = "yyyy-MM-dd") Date startTime,
            @DateTimeFormat(pattern = "yyyy-MM-dd") Date endTime,
            String chldrenId,
            String classesId,
            String name,
            String leaveType,
            String type
            ) throws IOException {
        List<String> collect =new ArrayList<>();
        // 获取所有数据（不分页）
        Page<ChildrenLeaveRequest> childrenLeaveRequests = childrenLeaveRequestService.selChildrenLeaveRequest(
                aid, startTime, chldrenId, classesId, name, leaveType, type, 0, 99999, collect);

        List<ChildrenLeaveRequest> content = childrenLeaveRequests.getContent();

        // 处理班级名称（与列表查询保持一致）
        for (ChildrenLeaveRequest item : content) {
            Classes classes = classesService.selectClassById(item.getClassesId());
            if (classes != null) {
                item.setClassesName(classes.getName());
            }
        }

        // 设置响应头
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        String fileName = "宝宝请假信息导出_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".xlsx";
        String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName);

        // 使用SXSSFWorkbook支持大数据量
        SXSSFWorkbook workbook = new SXSSFWorkbook(100);
        Sheet sheet = workbook.createSheet("宝宝请假信息");

        // 创建表头
        Row headerRow = sheet.createRow(0);
        String[] headers = {"班级", "开始时间", "结束时间", "请假内容", "宝宝姓名", "确认状态"};

        // 表头样式
        Font headerFont = workbook.createFont();
        headerFont.setFontName("宋体");
        headerFont.setBold(true);
        CellStyle headerStyle = workbook.createCellStyle();
        headerStyle.setFont(headerFont);
        headerStyle.setAlignment(HorizontalAlignment.CENTER);
        headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        // 填充表头
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
            cell.setCellStyle(headerStyle);
        }

        // 数据样式
        CellStyle dataStyle = workbook.createCellStyle();
        dataStyle.setAlignment(HorizontalAlignment.LEFT);

        // 日期样式
        CellStyle dateStyle = workbook.createCellStyle();
        dateStyle.cloneStyleFrom(dataStyle);
        CreationHelper createHelper = workbook.getCreationHelper();
        dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm"));

        // 填充数据
        int rowNum = 1;
        for (ChildrenLeaveRequest item : content) {
            Row row = sheet.createRow(rowNum++);

            // 班级名称
            Cell cell0 = row.createCell(0);
            cell0.setCellValue(item.getClassesName() != null ? item.getClassesName() : "");
            cell0.setCellStyle(dataStyle);

            // 开始时间
            Cell cell1 = row.createCell(1);
            if (item.getStartTime() != null) {
                cell1.setCellValue(item.getStartTime());
                cell1.setCellStyle(dateStyle);
            } else {
                cell1.setCellValue("");
                cell1.setCellStyle(dataStyle);
            }

            // 结束时间
            Cell cell2 = row.createCell(2);
            if (item.getEndTime() != null) {
                cell2.setCellValue(item.getEndTime());
                cell2.setCellStyle(dateStyle);
            } else {
                cell2.setCellValue("");
                cell2.setCellStyle(dataStyle);
            }

            // 请假内容
            row.createCell(3).setCellValue(item.getLeaveContent() != null ? item.getLeaveContent() : "");
            row.getCell(3).setCellStyle(dataStyle);

            // 宝宝姓名
            row.createCell(4).setCellValue(item.getName() != null ? item.getName() : "");
            row.getCell(4).setCellStyle(dataStyle);

            // 确认状态
            String stateStr = "未知";
            if ("0".equals(item.getState())) stateStr = "未确认";
            else if ("1".equals(item.getState())) stateStr = "已确认";
            else if ("2".equals(item.getState())) stateStr = "已取消";
            row.createCell(5).setCellValue(stateStr);
            row.getCell(5).setCellStyle(dataStyle);
        }

        // 手动调整列宽（替代autoSizeColumn）
        sheet.setColumnWidth(0, 5000); // 班级
        sheet.setColumnWidth(1, 5000); // 开始时间
        sheet.setColumnWidth(2, 5000); // 结束时间
        sheet.setColumnWidth(3, 8000); // 请假内容
        sheet.setColumnWidth(4, 5000); // 宝宝姓名
        sheet.setColumnWidth(5, 5000); // 确认状态

        // 写入响应流
        try {
            workbook.write(response.getOutputStream());
            response.getOutputStream().flush();
        } catch (IOException e) {
            throw new RuntimeException("导出文件写入失败", e);
        } finally {
            workbook.close();
            workbook.dispose();
        }
    }










    /**
     * 新增疫苗分类
     */
    @PostMapping("/addVaccineNotifications")
    public StatusResponse addVaccineNotifications(@RequestBody VaccineNotifications vaccineNotifications){
        vaccineNotificationsService.addVaccineNotifications(vaccineNotifications);
        return StatusResponse.success();
    }



    /**
     * 疫苗分类查询
     */
    @GetMapping("/selVaccineNotifications")
    public StatusResponse selVaccineNotifications(String name,String childrenId,Integer pageNum, Integer pageSize){
        Page<VaccineNotifications> page = vaccineNotificationsService.selVaccineNotifications(name,pageNum,pageSize);
        for (int i=0;i<page.getContent().size();i++){
            if (StringUtils.isNotEmpty(childrenId)){
                List<ChildrenVaccine> childrenVaccines = childrenVaccineService.selChildrenLeaveRequestList(null,childrenId,page.getContent().get(i).getId(),1);
                if (childrenVaccines!=null&&childrenVaccines.size()>0){
                    Date inoculateTime = childrenVaccines.get(0).getInoculateTime(); //接种时间
                    page.getContent().get(i).setInoculateTime(inoculateTime);
                    page.getContent().get(i).setState(1);
                }
            }
        }
        return StatusResponse.success(page);
    }



    /**
     * 疫苗分类刪除
     */
    @GetMapping("/delVaccineNotifications")
    public StatusResponse delVaccineNotifications(String id){
        vaccineNotificationsService.delVaccineNotifications(id);
        return StatusResponse.success();
    }



    /**
     * 批量新增新增宝宝疫苗信息
     */
    @PostMapping("/addChildrenVaccine")
    public StatusResponse addChildrenVaccine(@RequestBody ChildrenVaccine childrenVaccine) {
        childrenVaccine.setCreateTime(new Date());
        // 查询出已经新增过疫苗信息的宝宝信息
        List<ChildrenVaccine> yxz = childrenVaccineService.selChildrenLeaveRequestList(childrenVaccine.getClassesId(), childrenVaccine.getChildrenId(), childrenVaccine.getType(), null);

        // 如果 yxz 不为空，则移除当前数据
        if (yxz != null && !yxz.isEmpty()) {
//                iterator.remove();
//
            return StatusResponse.error("500", "该学生已有该疫苗的接种记录了");
        }

        // 将去重后的数据提交到服务层进行新增操作
        childrenVaccineService.addChildrenLeaveRequest(childrenVaccine);
        return StatusResponse.success();
    }




    /**
     * 批量新增新增宝宝疫苗信息
     */
    @PostMapping("/addChildrenVaccines")
    public StatusResponse addChildrenVaccines(@RequestBody List<ChildrenVaccine> childrenVaccines){
        Iterator<ChildrenVaccine> iterator = childrenVaccines.iterator();
        while (iterator.hasNext()) {
            ChildrenVaccine childrenVaccine = iterator.next();
            childrenVaccine.setCreateTime(new Date());

            // 查询出已经新增过疫苗信息的宝宝信息
            List<ChildrenVaccine> yxz = childrenVaccineService.selChildrenLeaveRequestList(childrenVaccine.getClassesId(), childrenVaccine.getChildrenId(), childrenVaccine.getType(), null);

            // 如果 yxz 不为空，则移除当前数据
            if (yxz != null && !yxz.isEmpty()) {
//                iterator.remove();
                return StatusResponse.error("500","该学生已有该疫苗的接种记录了");
            }

        }
        // 将去重后的数据提交到服务层进行新增操作
        childrenVaccineService.addChildrenLeaveRequests(childrenVaccines);
        return StatusResponse.success();
    }

//
//    /**
//     * 宝宝疫苗信息列表查询
//     */
//    @GetMapping("/selChildrenVaccinesPage")
//    public StatusResponse selChildrenVaccinesPage(String classesId,String chldrenId, String type,Integer state,String name,Integer pageNum,Integer pageSize){
//        Page<ChildrenVaccine> childrenVaccines = childrenVaccineService.selChildrenLeaveRequest(classesId,chldrenId,type,state,name, pageNum, pageSize);
//        List<ChildrenVaccine> content = childrenVaccines.getContent();
//        for (int i=0;i<content.size();i++){
//            ChildrenVaccine childrenVaccine = content.get(i);
//            Children children = childrenService.getById (childrenVaccine.getChildrenId());
//            if(children!=null){
//                childrenVaccine.setAge(calculateBabyAgeInMonths(children.getBirthday()));
//            }
//        }
//        return StatusResponse.success(childrenVaccines);
//    }





    @GetMapping("/selChildrenVaccinesPage")
    public StatusResponse selChildrenVaccinesPage(@RequestHeader(TICKET) String ticket,String aid,String classesId, String chldrenId, String type, Integer state, String name, Integer pageNum, Integer pageSize) {
//        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
//        if ("老师".equals(staffRole.getRoleName())) {
//            if (classesId == null||classesId.equals("")){
//                classesId="999";
//            }
//        }



        PagerQuery pagerQuery =new PagerQuery();
        pagerQuery.setPageNum(0);
        pagerQuery.setPageSize(9999);

        //根据班级id查询宝宝列表
        Page<Children> childrens = classesService.getChildIdsByClassesId(aid,classesId,pagerQuery);

        //所有宝宝信息
        List<Children> contentAll = childrens.getContent();


        //最终返回结果
        List<ChildrenVaccine> rstChildrenVaccines = new ArrayList<>();

        for (int i=0;i<contentAll.size();i++){

            ChildrenVaccine childrenVaccine =new ChildrenVaccine();
            childrenVaccine.setType(type);
            childrenVaccine.setChildrenId(contentAll.get(i).getId()); //宝宝id
            childrenVaccine.setClassesId(classesId); //班级id
            childrenVaccine.setName(contentAll.get(i).getName()); //宝宝名字

            Page<ChildrenVaccine> childrenVaccines = childrenVaccineService.selChildrenLeaveRequest(null, classesId, contentAll.get(i).getId(), type, null, null, 0, 9999);
            if (childrenVaccines.getContent()!=null){
                if (childrenVaccines.getContent().size()>0){
                    childrenVaccine.setState(childrenVaccines.getContent().get(0).getState());
                    childrenVaccine.setInoculateTime(childrenVaccines.getContent().get(0).getInoculateTime());
                    childrenVaccine.setRemark(childrenVaccines.getContent().get(0).getRemark());
                    childrenVaccine.setCreateTime(childrenVaccines.getContent().get(0).getCreateTime());
                    childrenVaccine.setCreateUserId(childrenVaccines.getContent().get(0).getCreateUserId());
                    childrenVaccine.setCreateUserName(childrenVaccines.getContent().get(0).getCreateUserName());
                }else {
                    childrenVaccine.setState(0);
                }
            }else {
                childrenVaccine.setState(0);
            }
            rstChildrenVaccines.add(childrenVaccine);
        }

        // 根据state和name进行数据筛选
        rstChildrenVaccines = rstChildrenVaccines.stream()
                .filter(item -> {
                    boolean stateMatch = true;
                    boolean nameMatch = true;

                    // state筛选：如果state参数不为null，则进行匹配
                    if (state != null) {
                        stateMatch = item.getState() != null && item.getState().equals(state);
                    }

                    // name筛选：如果name参数不为null且不为空，则进行模糊匹配
                    if (name != null && !name.trim().isEmpty()) {
                        nameMatch = item.getName() != null && item.getName().toLowerCase().contains(name.toLowerCase().trim());
                    }

                    return stateMatch && nameMatch;
                })
                .collect(Collectors.toList());

        // 物理分页完善
        int total = rstChildrenVaccines.size();
        int startIndex = pageNum * pageSize;
        int endIndex = Math.min(startIndex + pageSize, total);

        // 如果起始索引超出范围，返回空列表
        if (startIndex >= total) {
            startIndex = total;
            endIndex = total;
        }
        List<ChildrenVaccine> pagedList = rstChildrenVaccines.subList(startIndex, endIndex);


        // 设置年龄信息
        for (ChildrenVaccine childrenVaccine : pagedList) {
            try {
                Children children = childrenService.getById(childrenVaccine.getChildrenId());
                if (children != null && children.getBirthday() != null) {
                    childrenVaccine.setAge(calculateBabyAgeInMonths(children.getBirthday()));
                } else {
                    // 记录日志或设置默认年龄
                    childrenVaccine.setAge(0); // 或其他默认值
                    log.warn("Children not found or birthday is null for id: {}", childrenVaccine.getChildrenId());
                }
            } catch (EntityNotFoundException e) {
                // 处理实体不存在的异常
                childrenVaccine.setAge(0); // 或其他默认值
                log.error("Failed to load children entity for id: {}", childrenVaccine.getChildrenId(), e);
            }
        }

        // 创建分页结果对象
        Page<ChildrenVaccine> childrenVaccines = new PageImpl<>(
                pagedList,
                PageRequest.of(pageNum, pageSize),
                total
        );

        return StatusResponse.success(childrenVaccines);
    }






    // 计算宝宝月龄的方法
    public int calculateBabyAgeInMonths(Date birthday) {
        // 将Date转换为LocalDate
        LocalDate birthDate = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        // 获取当前日期
        LocalDate currentDate = LocalDate.now();
        // 计算两个日期之间的差值
        Period period = Period.between(birthDate, currentDate);
        // 计算总月龄
        int ageInMonths = period.getYears() * 12 + period.getMonths();
        return ageInMonths;
    }



    /**
     * 宝宝已接种疫苗信息详情查询
     */
    @GetMapping("/selChildrenVaccinesDetails")
    public StatusResponse selChildrenVaccinesDetails(String id){
        List<ChildrenVaccine> childrenVaccines = childrenVaccineService.selChildrenLeaveRequestList(null,id,null,1);
        return StatusResponse.success(childrenVaccines);
    }


    /**
     * 宝宝已接种疫苗信息详情查询
     */
    @GetMapping("/selChildrenVaccinesDetailsOne")
    public StatusResponse selChildrenVaccinesDetailsOne(String id){
        ChildrenVaccine childrenVaccines = childrenVaccineService.selChildrenVaccineById(id);
        return StatusResponse.success(childrenVaccines);
    }




    /**
     * 班级信息数据统计
     */
    @GetMapping("/selClassDataStatistics")
    public StatusResponse selClassDataStatistics(String classesId,String type){
       List<RelClassesChildren>  relClassesChildren=relClassesChildrenRepository.findAllByClassesIdAndStatus(classesId,1);
       //班级人数
        int size = relClassesChildren.size();


        //总人数
        List<ChildrenVaccine> childrenVaccines = childrenVaccineService.selChildrenLeaveRequestList(classesId,null, type, null);

        //未接种
        List<ChildrenVaccine> childrenVaccines0 = childrenVaccineService.selChildrenLeaveRequestList(classesId,null, type, 0);

        //已接种
        List<ChildrenVaccine> childrenVaccines1 = childrenVaccineService.selChildrenLeaveRequestList(classesId,null, type, 1);
        int vaccinatedCount = getUniqueChildCount(childrenVaccines1);


        Map map =new HashMap();
        map.put("headcount",size); //总人数
        map.put("unvaccinated",size-vaccinatedCount); //未接种
        map.put("vaccinated",vaccinatedCount); //已接种

        return StatusResponse.success(map);
    }

    /**
     * 工具方法：按childrenId去重，返回唯一宝宝数
     * 处理列表为null或空的情况，避免空指针
     */
    private int getUniqueChildCount(List<ChildrenVaccine> vaccineList) {
        if (CollectionUtils.isEmpty(vaccineList)) {
            return 0;
        }
        // 提取不重复的childrenId（Set自动去重）
        Set<String> uniqueChildIds = vaccineList.stream()
                .map(ChildrenVaccine::getChildrenId)
                .filter(childId -> childId != null && !childId.isEmpty()) // 过滤空的childrenId
                .collect(Collectors.toSet());
        return uniqueChildIds.size();
    }

    /**
     * 编辑宝宝疫苗信息
     */
    @PostMapping("/editChildrenVaccines")
    public StatusResponse editChildrenVaccines(@RequestBody ChildrenVaccine childrenVaccines){

        List<ChildrenVaccine> yxz = childrenVaccineService.selChildrenLeaveRequestList(childrenVaccines.getClassesId(), childrenVaccines.getChildrenId(), childrenVaccines.getType(), null);

//        // 如果 yxz 不为空，则说明已经打过了
//        if (yxz != null && !yxz.isEmpty()) {
//            return StatusResponse.error("500","该学生已有该疫苗的接种记录了");
//        }

        ChildrenVaccine childrenVaccine = childrenVaccineService.selChildrenVaccineById(childrenVaccines.getId());
        childrenVaccine.setInoculateTime(childrenVaccines.getInoculateTime()); //接种时间
        childrenVaccine.setType(childrenVaccines.getType()); //类型
        childrenVaccine.setRemark(childrenVaccines.getRemark()); //备注
        childrenVaccine.setState(childrenVaccines.getState()); //接种状态
        childrenVaccineService.addChildrenLeaveRequest(childrenVaccines);
        return StatusResponse.success();
    }




    /**
     * 删除宝宝疫苗信息
     */
    @PostMapping("/delChildrenVaccines")
    public StatusResponse delChildrenVaccines(ChildrenVaccine childrenVaccines){
        childrenVaccineService.delChildrenVaccines(childrenVaccines.getId());
        return StatusResponse.success();
    }



    /**
     * 新增宝宝疫苗信息
     */
    @PostMapping("/addChildrenVaccinesOne")
    public StatusResponse addChildrenVaccinesOne(@RequestBody ChildrenVaccine childrenVaccines){

        //通过宝宝id和type查询对应的疫苗信息。
        ChildrenVaccine childrenVaccinesOne = childrenVaccineService.selChildrenVaccineByChildrenId(childrenVaccines.getChildrenId(), childrenVaccines.getType());
        if (childrenVaccinesOne!=null){ //说明已经打过这个类型的疫苗了修改状态即可。
            if (childrenVaccinesOne.getState() == 1){
                return StatusResponse.error("500","已接种该疫苗");
            }
            childrenVaccinesOne.setState(1); //已接种
            childrenVaccineService.addChildrenLeaveRequest(childrenVaccinesOne);
            return StatusResponse.success();
        }
        //如果没打过该类型的疫苗直接新增即可
        childrenVaccines.setCreateTime(new Date());
        childrenVaccineService.addChildrenLeaveRequest(childrenVaccines);
        return StatusResponse.success();
    }




































    @ApiOperation(value = "WEB 编辑宝宝信息",httpMethod = "POST")
    @ApiImplicitParams({
    	@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "id", value = "宝宝id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "childrenName", value = "宝宝名称", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "nickName", value = "宝宝昵称", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "gender", value = "性别， 0：女，1：男", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "birthday", value = "生日，格式:yyyy-MM-dd", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "weight", value = "体重 ：数字", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "height", value = "身高 ：数字", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "header", value = "头围 ：数字", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "address", value = "地址", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "remark", value = "备注", required = false, dataType = "string"),
    })
    @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期"),
  		@ApiResponse(code = 000002, message = "用户没有对应园区"),
  		@ApiResponse(code = 000005, message = "课时必须为数字")
  	}) 
    @RequestMapping(value = "/edit_base_info", method = RequestMethod.POST)
    public StatusResponse edit(@RequestHeader(TICKET) String ticket,
                               String id, String childrenName, String nickName, String birthday, int gender, String weight, String height, String header, String address, String remark) throws AccessDeniedException {
        String areaId = cache.getAreaId(ticket);
        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
        if ("老师".equals(staffRole.getRoleName())||"其他".equals(staffRole.getRoleName())) {
            return StatusResponse.error ("100023","权限不足");  // 返回403
        }
        return StatusResponse.success(childrenService.edit(areaId, id, childrenName, nickName, birthday, gender, weight, height, header, address, remark));
    }


    @ApiOperation(value = "获取宝贝的简要信息以及班级信息", httpMethod = "POST", hidden = false)
    @RequestMapping("/list_for_crm")
    public StatusResponse listForCrm(@RequestHeader(TICKET) String ticket, Integer category, String childName, String classId, String crmClienteleIds) throws AccessDeniedException {
        StaffDTO baseInfo = cache.getStaff(ticket);
        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
        if ("老师".equals(staffRole.getRoleName())||"其他".equals(staffRole.getRoleName())) {
            return StatusResponse.error ("100023","权限不足");  // 返回403
        }
        List<String> ids = null;
        if (StringUtils.isNotBlank(crmClienteleIds)){
            ids = Arrays.asList(crmClienteleIds.split("\\|"));
        }

        List result = childrenService.getChildrenClassInfoForCrm(baseInfo.getAreaId(), category, childName, classId, ids);
        return StatusResponse.success(result);
    }



    @ApiOperation(value = "获取宝贝的简要信息以及班级信息", httpMethod = "POST", hidden = false)
    @RequestMapping("/list_for_crmV2")
    public StatusResponse list_for_crmV2(@RequestHeader(TICKET) String ticket,  String childName, String classId, String crmClienteleIds) throws AccessDeniedException {
        StaffDTO baseInfo = cache.getStaff(ticket);
        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
        if ("老师".equals(staffRole.getRoleName())||"其他".equals(staffRole.getRoleName())) {
            return StatusResponse.error ("100023","权限不足"); // 返回403
        }
        List<String> ids = null;
        if (StringUtils.isNotBlank(crmClienteleIds)){
            ids = Arrays.asList(crmClienteleIds.split("\\|"));
        }

        List result = childrenService.getChildrenClassInfoForCrmV2(baseInfo.getAreaId(),  childName, classId, ids);
        return StatusResponse.success(result);
    }

    @ApiOperation(value = "宝宝列表",httpMethod = "POST")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "name", value = "宝宝名称", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "category", value = "班级类型  0：托班+早教  1：托班 2：早教", required = false, dataType = "integer"),
		@ApiImplicitParam(paramType = "formData", name = "status", value = "班级类型  -1：全部  0：未生效  1：正常 2：合同结束  3：已退学  4：已毕业", required = false, dataType = "integer"),
		@ApiImplicitParam(paramType = "formData", name = "nurseryStatus", value = "托班状态 0：已结束  1：进行中", required = false, dataType = "integer"),
		@ApiImplicitParam(paramType = "formData", name = "earlyStatus", value = "早教状态 0：已结束 1：进行中", required = false, dataType = "integer"),
		@ApiImplicitParam(paramType = "formData", name = "pageNum", value = "当前页码", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "pageSize", value = "每页多少条", required = false, dataType = "string"),
    })
    @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期")
  	}) 
    @RequestMapping(value = "/page", method = RequestMethod.POST)
    public StatusResponse page(@RequestHeader(TICKET) String ticket, ChildrenQuery query) throws AccessDeniedException {
        String areaId = cache.getAreaId(ticket);
        RoleDTO staffRole = ssoCallService.getStaffRole(ticket);
        if ("老师".equals(staffRole.getRoleName())||"其他".equals(staffRole.getRoleName())) {
            return StatusResponse.error ("100023","权限不足"); // 返回403
        }
        query.setAreaId(areaId);
        Page<WebChildrenVo> page = childrenService.page(query);
        return StatusResponse.success(page);
    }

    @ApiOperation(value = "WEB 宝宝联系人",consumes="application/x-www-form-urlencoded",httpMethod = "POST")
    @ApiImplicitParams({
    	@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
    	@ApiImplicitParam(paramType = "query", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期")
	}) 
    @RequestMapping(value = "/children_link_mans")
    public StatusResponse childrenLinkMans(String childrenId) {
        List<AppUserDetailVo> users = childrenService.getAppUsersByChildrenId(childrenId);
        return StatusResponse.success(users);
    }

    @ApiOperation(value = "WEB 添加宝宝联系人",consumes="application/x-www-form-urlencoded",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "id", value = "id （修改传入）", required = false, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "name", value = "姓名", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "phone", value = "电话", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "company", value = "公司", required = false, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "email", value = "邮箱", required = false, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "relation", value = "关系", required = false, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "remark", value = "备注", required = false, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "cameraEnabled", value = "监控开关", required = false, dataType = "boolean"),
            @ApiImplicitParam(paramType = "formData", name = "wechatEnabled", value = "微信绑定开关", required = false, dataType = "boolean"),
            @ApiImplicitParam(paramType = "formData", name = "templateMsgEnabled", value = "模板消息开关", required = false, dataType = "boolean"),
            @ApiImplicitParam(paramType = "formData", name = "teacherChatEnabled", value = "老师聊天开关", required = false, dataType = "boolean"),

    })
    @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期"),
  		//@ApiResponse(value = 000009, message = "手机号已经存在"),
  		@ApiResponse(code = 000106, message = "宝宝不存在")
  	}) 
    @RequestMapping(value = "/add_children_link_mans")
    public StatusResponse addChildrenLinkMans(@RequestParam(required = true) String childrenId, ParentUser parentUser) {
        if (StringUtils.isBlank(parentUser.getName()) || StringUtils.isBlank(parentUser.getPhone()))
            throw new BusinessException(ErrorCode.SIGN_ERROR, "姓名或电话不能为空！");

        return StatusResponse.success(childrenService.addChildrenLinkMans(childrenId, parentUser));
    }

    @ApiOperation(value = "WEB 修改宝宝联系人权限配置",consumes="application/x-www-form-urlencoded",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "id", value = "联系人id", required = true, dataType = "string"),
            @ApiImplicitParam(paramType = "formData", name = "rid", value = "关系id", required = true, dataType = "string"),

            @ApiImplicitParam(paramType = "formData", name = "cameraEnabled", value = "监控开关", required = false, dataType = "boolean"),
            @ApiImplicitParam(paramType = "formData", name = "wechatEnabled", value = "微信绑定开关", required = false, dataType = "boolean"),
            @ApiImplicitParam(paramType = "formData", name = "templateMsgEnabled", value = "模板消息开关", required = false, dataType = "boolean"),
            @ApiImplicitParam(paramType = "formData", name = "teacherChatEnabled", value = "老师聊天开关", required = false, dataType = "boolean"),

    })
    @ApiResponses({
            @ApiResponse(code = 000000, message = "成功"),
            @ApiResponse(code = 000001, message = "ticket已过期"),
            //@ApiResponse(value = 000009, message = "手机号已经存在"),
            @ApiResponse(code = 000106, message = "宝宝不存在")
    })
    @RequestMapping(value = "/update_children_link_mans")
    public StatusResponse updateChildrenLinkMans(@RequestParam(required = true) String childrenId, ParentUser parentUser) {
        if(StringUtils.isBlank(parentUser.getId()) || StringUtils.isBlank(parentUser.getRid()) || StringUtils.isBlank(childrenId)){
            throw new com.matt.commons.exception.BusinessException(ErrorCode.SIGN_ERROR,"参数错误！");
        }

        return StatusResponse.success(childrenService.updateChildrenLinkMans(childrenId, parentUser));
    }

    @ApiOperation(value = "WEB 删除宝宝联系人",consumes="application/x-www-form-urlencoded",httpMethod = "POST")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "id", value = "id （修改传入）", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),
    })
    @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期"),
  		//@ApiResponse(value = 000009, message = "手机号已经存在"),
  		@ApiResponse(code = 000106, message = "宝宝不存在")
  	}) 
    @RequestMapping(value = "/del_children_link_mans")
    public StatusResponse delChildrenLinkMans(@RequestParam(required = true) String id,
                                              @RequestParam(required = true) String childrenId) {
        return StatusResponse.success(childrenService.delChildrenLinkMans(childrenId, id));
    }

//    @ApiOperation(value = "WEB 园区所有学生",httpMethod = "POST")
//    @ApiImplicitParams({
//		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),
//		@ApiImplicitParam(paramType = "formData", name = "name", value = "宝宝名称", required = false, dataType = "string"),
//		@ApiImplicitParam(paramType = "formData", name = "value", value = "学籍号", required = false, dataType = "string"),
//		@ApiImplicitParam(paramType = "formData", name = "pageNum", value = "当前页码", required = false, dataType = "string"),
//		@ApiImplicitParam(paramType = "formData", name = "pageSize", value = "每页多少条", required = false, dataType = "string"),
//    })
//    @ApiResponses({
//		@ApiResponse(code = 000000, message = "成功"),
//		@ApiResponse(code = 000001, message = "ticket已过期"),
//		@ApiResponse(code = 000002, message = "用户没有对应园区")
//	})
//    @RequestMapping(value = "/page_by_area", method = RequestMethod.POST)
//    public StatusResponse pageByArea(ChildrenQuery query) {
//        Page<Children> page = childrenService.findChildrenPage(query);
//        return StatusResponse.success(page);
//    }

    @ApiOperation(value = "WEB 园区所有宝宝",httpMethod = "POST")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "name", value = "宝宝名称", required = false, dataType = "string"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期"),
		@ApiResponse(code = 000002, message = "用户没有对应园区")
	}) 
    @RequestMapping(value = "/all_by_area", method = RequestMethod.POST)
    public StatusResponse allByArea(@RequestHeader(TICKET) String ticket, String name) {
        String areaId = cache.getAreaId(ticket);
        List<ChildrenListVo> childrenList = childrenService.getChildrenByArea(areaId, name);
        return StatusResponse.success(childrenList);
    }

    @ApiOperation(value = "所有托班有效的宝宝",httpMethod = "POST")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "name", value = "宝宝名称", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "nurseryStatus", value = "托班状态1进行中，0已结束", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "pageNum", value = "当前页码", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "pageSize", value = "每页多少条", required = false, dataType = "string"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期"),
		@ApiResponse(code = 000002, message = "用户没有对应园区")
	}) 
    @RequestMapping(value = "/nursery_valid_list", method = RequestMethod.POST)
    public StatusResponse nurseryValidList(ChildrenNurseryQuery query) {
        Page<ChildrenNurseryListDO> childrenList = childrenService.getNurseryValidChildren(query);
        return StatusResponse.success(childrenList);
    }

    @ApiOperation(value = "托班转班",httpMethod = "POST")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "classesId", value = "班级id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "childrenId", value = "孩子id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "oldClassesId", value = "之前的班级id", required = false, dataType = "string"),
		@ApiImplicitParam(paramType = "formData", name = "remark", value = "备注", required = false, dataType = "string"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期"),
		@ApiResponse(code = 000002, message = "用户没有对应园区")
	}) 
    @RequestMapping(value = "nursery_transfer")
    public StatusResponse nurseryTransfer(@RequestHeader(TICKET) String ticket, String classesId, String childrenId, String oldClassesId, String remark) {
        if (StringUtils.isNotBlank(classesId) && StringUtils.isNotBlank(oldClassesId) && classesId.equals(oldClassesId))
            return StatusResponse.error(ErrorCode.CLASSES_IS_SAME, "不能在同一个班级转班！");
        Boolean result = childrenService.nurseryTransfer(classesId, childrenId, cache.getStaffId(ticket), remark, oldClassesId);
        return StatusResponse.success(result);
    }

    @ApiOperation(value = "园区孩子数",httpMethod = "POST")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),		
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期")
	}) 
    @RequestMapping(value = "/non_course_children", method = RequestMethod.POST)
    public StatusResponse nonCourseChildren(@RequestHeader(TICKET) String ticket) {
        String areaId = cache.getAreaId(ticket);
        List<ChildrenListVo> childrenList = childrenService.getHasChildrenByArea(areaId);
        return StatusResponse.success(childrenList);
    }

    @ApiOperation(value = "没有排班宝宝列表",httpMethod = "GET")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区ID", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "category", value = "班级类型", required = true, dataType = "integer"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期"),
		@ApiResponse(code = 000002, message = "用户没有对应园区")
	}) 
    @RequestMapping(value = "/list_non_classes")
    public StatusResponse listByClassesType(@RequestHeader(TICKET) String ticket, @RequestParam(defaultValue = "1") Integer category) {
        String areaId = cache.getAreaId(ticket);
        List<ChildrenListDO> childrenList = childrenService.getChildrenNonClassesNurseryValid(areaId, category);
        return StatusResponse.success(childrenList);
    }

    @ApiOperation(value = "WEB 查看宝宝详情",httpMethod = "POST",consumes="application/x-www-form-urlencoded", notes="包含宝宝基本信息，宝宝联系人信息")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期"),
		@ApiResponse(code = 000002, message = "用户没有对应园区"),
		@ApiResponse(code = 800000, message = "日期格式错误")
	}) 
    @RequestMapping(value = "/detail", method = RequestMethod.POST)
    public StatusResponse detail(String childrenId) {
        Map response = childrenService.childrenDetailById(childrenId);
        return StatusResponse.success(response);
    }

    @ApiOperation(value = "WEB 获取宝宝信息",httpMethod = "POST",consumes="application/x-www-form-urlencoded", notes="通过宝宝姓名，出生日期 获取宝宝信息, ")
    @ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "childrenName", value = "宝宝名称", required = true, dataType = "string"),
		@ApiImplicitParam(paramType = "query", name = "birthday", value = "出生日期 格式：yyyy-MM-dd", required = true, dataType = "string"),
    })
    @ApiResponses({
		@ApiResponse(code = 000000, message = "成功"),
		@ApiResponse(code = 000001, message = "ticket已过期"),
		@ApiResponse(code = 000002, message = "用户没有对应园区"),
		@ApiResponse(code = 800000, message = "日期格式错误")
	}) 
    @RequestMapping(value = "/query_info", method = RequestMethod.POST)
    @ResponseBody
    public StatusResponse queryInfo(@RequestHeader(TICKET) String ticket, String childrenName, String birthday) {
        String areaId = cache.getAreaId(ticket);
        Children children = childrenService.getByNameAndBirthday(childrenName, DateUtil.parseToDate(birthday), areaId);
        Map response = new HashMap();
        if (Objects.nonNull(children)) {
            List<AppUserDetailVo> users = childrenService.getAppUsersByChildrenId(children.getId());
            response.put("users", users);
        }
        response.put("children", children);
        return StatusResponse.success(response);
    }

    @ApiOperation(value = "退学",httpMethod = "POST")
    @ApiImplicitParams({
  		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
  		//@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区Id", required = true, dataType = "string"),
  		@ApiImplicitParam(paramType = "query", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),
  		@ApiImplicitParam(paramType = "query", name = "reason", value = "退学理由", required = true, dataType = "string"), 
  		@ApiImplicitParam(paramType = "query", name = "backMoney", value = "退学金额", required = true, dataType = "string"), 
    })
      @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期")
  	}) 
    @RequestMapping(value = "/drop_out", method = RequestMethod.POST)
    @ResponseBody
    public StatusResponse dropOut(@RequestHeader(TICKET) String ticket,  String childrenId, String reason,String backMoney) {
        Children children = childrenService.dropOut(cache.getStaff(ticket), childrenId, reason,backMoney);
        return StatusResponse.success(children);
    }

    @ApiOperation(value = "毕业",httpMethod = "POST")
    @ApiImplicitParams({
  		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
  		@ApiImplicitParam(paramType = "query", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),	
    })
      @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期"),
  		@ApiResponse(code = 000210, message = "所有合同结束后才能毕业")

  	}) 
    @RequestMapping(value = "/graduate", method = RequestMethod.POST)
    @ResponseBody
    public StatusResponse graduate(@RequestHeader(TICKET) String ticket, String childrenId) {
        String areaId = cache.getAreaId(ticket);
        Children children = childrenService.graduate(cache.getStaff(ticket), areaId, childrenId);
        return StatusResponse.success(children);
    }

//    @ApiOperation(value = "绑定宝宝列表",httpMethod = "POST")
//    @ApiImplicitParams({
//  		@ApiImplicitParam(paramType = "query", name = "areaId", value = "园区ID", required = true, dataType = "string"),
//  		@ApiImplicitParam(paramType = "query", name = "name", value = "宝宝姓名", required = false, dataType = "string"),
//    })
//      @ApiResponses({
//  		@ApiResponse(code = 000000, message = "成功"),
//  		@ApiResponse(code = 000001, message = "ticket已过期")
//  	})
//    @RequestMapping(value = "/evaluating_cb_bind_list", method = RequestMethod.POST)
//    public StatusResponse bindList(String areaId, String name) {
//        List<ChildrenListVo> childrenList = childrenService.getEvaluatingCBBindList(areaId, name);
//        return StatusResponse.success(childrenList);
//    }
//
//    @ApiOperation(value = "绑定宝宝",httpMethod = "POST")
//    @ApiImplicitParams({
//  		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
//  		@ApiImplicitParam(paramType = "query", name = "evaluatingCBRecordId", value = "初评记录id", required = true, dataType = "string"),
//  		@ApiImplicitParam(paramType = "query", name = "childrenId", value = "宝宝id", required = true, dataType = "string"),
//    })
//      @ApiResponses({
//  		@ApiResponse(code = 000000, message = "成功"),
//  		@ApiResponse(code = 000001, message = "ticket已过期")
//  	})
//    @RequestMapping(value = "/evaluating_cb_bind", method = RequestMethod.POST)
//    public StatusResponse bindEvaluatingCB(String evaluatingCBRecordId, String childrenId) {
//        Boolean result = childrenService.bindEvaluatingCB(evaluatingCBRecordId, childrenId);
//        return StatusResponse.success(result);
//    }

    @ApiOperation(value = "上传附件",httpMethod = "POST")
    @ApiImplicitParams({
  		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
  		@ApiImplicitParam(paramType = "formData", name = "file", value = "文件", required = true, dataType = "file"),	
  		@ApiImplicitParam(paramType = "formData", name = "cid", value = "宝宝id", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "formData", name = "attaType", value = "文件类型 0附件 1评测 默认0", required = true, dataType = "string"),	

    })
      @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期")
  	}) 
    @RequestMapping("/uploadAttrFile")
    public StatusResponse uploadFile(@RequestHeader(TICKET) String ticket, MultipartFile file, Atta atta) {
        StaffDTO baseInfo = cache.getStaff(ticket);
        atta.setUid(baseInfo.getId());
        atta.setUname(baseInfo.getRealName());
        String path = attaService.uploadFile(file, atta);
        return StatusResponse.success(path);
    }

    @ApiOperation(value = "获取附件列表",httpMethod = "POST")
    @ApiImplicitParams({
  		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
  		@ApiImplicitParam(paramType = "formData", name = "attaType", value = "文件类型 0 附件 1 评测 默认2全部", required = false, dataType = "string"),	
  		@ApiImplicitParam(paramType = "formData", name = "cid", value = "宝宝id", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "formData", name = "pageNum", value = "页码 默认 0 第一页", required = false, dataType = "integer"),	
  		@ApiImplicitParam(paramType = "formData", name = "pageSize", value = "分页大小 默认10 ", required = false, dataType = "integer"),	
    })
      @ApiResponses({
  		@ApiResponse(code = 000000, message = "成功"),
  		@ApiResponse(code = 000001, message = "ticket已过期")
  	}) 
    @RequestMapping("/getAttrList")
    public StatusResponse getAttrList(String cid, @RequestParam(required = false, defaultValue = "2") Integer attaType, PagerQuery pagerQuery) {
        Page page = attaService.getAllByCidAndType(cid, attaType, pagerQuery);
        return StatusResponse.success(page);
    }


    /**
     * 新增未激活宝宝
     *
     * @return
     */
    @ApiOperation(value = "WEB 添加宝宝",httpMethod = "POST")
    @ApiImplicitParams({
  		@ApiImplicitParam(paramType = "header", name = "ticket", value = "票据", required = true, dataType = "string"),
  		@ApiImplicitParam(paramType = "query", name = "childrenName", value = "宝宝名称", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "nickName", value = "宝宝昵称", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "gender", value = "性别， 0：女，1：男", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "birthday", value = "生日，格式:yyyy-MM-dd", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "address", value = "地址 ", required = false, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "name", value = "家长名字", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "phone", value = "家长手机号码", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "company", value = "家长的公司 ", required = false, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "relation", value = "关系， 数组", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "weight", value = "体重 ：数字", required = true, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "height", value = "身高 ：数字", required = false, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "header", value = "头围 ：数字 ", required = false, dataType = "string"),	
  		@ApiImplicitParam(paramType = "query", name = "remark", value = "备注", required = false, dataType = "string"),	
    })
    @ApiResponses({
            @ApiResponse(code = 000000, message = "成功"),
            @ApiResponse(code = 000001, message = "ticket已过期"),
            @ApiResponse(code = 000002, message = "用户没有对应园区"),
            @ApiResponse(code = 000005, message = "课时必须为数字")
    })
    @RequestMapping(value = "/create_child")
    public StatusResponse createChild(@RequestHeader(TICKET) String ticket,String childrenName, String nickName, Integer gender,
                                      String birthday, String address, String name, String phone, String company,
                                      String relation,String weight,String height,String header,String remark,String allergy,String diseasesHistory,String place,String province,String city,String district,String detailedAddress,String education,String position,String email) {
        String crmClienteleId = null ;
        Children children = Children.of_new(childrenName, Objects.isNull(nickName) ? "" : nickName, gender, DateUtil.parseToDate(birthday), cache.getAreaId(ticket), Objects.isNull(address) ? "" : address, crmClienteleId, cache.getStaffId(ticket), weight,height,header,remark,allergy,diseasesHistory,place);

        Children c = childrenService.add(children, phone, name, company, relation,province,city,district, detailedAddress, education, position,email);
        return StatusResponse.success(c);
    }


    @RequestMapping(value = "/export_excel", method = RequestMethod.POST)
    public StatusResponse exportExcel(@RequestHeader(TICKET) String ticket, ChildrenQuery query) {
        AreaDTO area = cache.getArea(ticket);

        query.setAreaId(area.getId());

        List<WebChildrenVo> childrenVoList = childrenService.nonPage(query);
 

        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("学籍管理");
        createRowIndex0(query,area,workbook,sheet);
        createRowIndex1(query,workbook, sheet);
        createRowIndexI(query,workbook, sheet, childrenVoList);
        mergedCell(workbook,sheet);


        sheet.setDefaultColumnWidth(17);
        sheet.setDefaultRowHeight((short) (2 * 256));
        sheet.setHorizontallyCenter(true);
        sheet.setVerticallyCenter(true);

        sheet.setColumnWidth(0,10 * 256);
        sheet.setColumnWidth(1,10 * 256);
        sheet.setColumnWidth(2,14 * 256);
        sheet.setColumnWidth(3,10 * 256);
        sheet.setColumnWidth(4,14 * 256);
        sheet.setColumnWidth(5,10 * 256);
        sheet.setColumnWidth(6,10 * 256);

        String uploadedResult = null;
        try{

            String uploadName = area.getName() + "(" + DateTime.now().toString("yyyyMMddHHmmss") + ")";
            String fileName = UUID.randomUUID().toString();
            String uploadPath = "teach/file/children_export_excel/" + DateTime.now().toString("yyyy-MM") + "/" + uploadName + ".xls";

            File outputFile = File.createTempFile(fileName,"xls");
            FileOutputStream fileOutputStream = new FileOutputStream(outputFile);

            workbook.write(fileOutputStream);
            String relativePath = ossProcessService.aliyunOssUpload(uploadPath, outputFile);
            uploadedResult = IMG_SERVICE_PREFIX + relativePath;
            outputFile.deleteOnExit();
            fileOutputStream.close();

        }catch (Exception e){
            e.printStackTrace();
        }

        return StatusResponse.success(uploadedResult);
    }

    private void createRowIndex0(ChildrenQuery query, AreaDTO area, HSSFWorkbook workbook, HSSFSheet sheet) {

        HSSFRow row0 = sheet.createRow(0);
        HSSFCell row0Cell0 = row0.createCell(0);
        row0Cell0.setCellValue(area.getName() + "学籍表");

        row0.setHeight((short) (2 * 256));

        CellStyle style = workbook.createCellStyle();
        PoiUtils.setupCellTableStyle(style);
        PoiUtils.setupCellTableHead(style);

        row0Cell0.setCellStyle(style);

    }

    private static void mergedCell(HSSFWorkbook workbook, HSSFSheet sheet) {
        HSSFRow row1 = sheet.getRow(1);
        sheet.addMergedRegion(new CellRangeAddress(0,0,0,row1.getLastCellNum() - 1));
    }

    private static void createRowIndex1(ChildrenQuery query,HSSFWorkbook workbook, HSSFSheet sheet) {

        HSSFCellStyle style = workbook.createCellStyle();
        PoiUtils.setupCellTableStyle(style);


        HSSFRow row1 = sheet.createRow(1);
        row1.setHeight((short) (2 * 256));
        //全部
        if(query.getCategory().intValue() == 0){

            row1.createCell(0).setCellValue("姓名");
            row1.createCell(1).setCellValue("月龄");
            row1.createCell(2).setCellValue("出生年月");
            row1.createCell(3).setCellValue("班级");

            row1.getCell(0).setCellStyle(style);
            row1.getCell(1).setCellStyle(style);
            row1.getCell(2).setCellStyle(style);
            row1.getCell(3).setCellStyle(style);
        }

        //托班
        if(query.getCategory().intValue() == 1){

            row1.createCell(0).setCellValue("姓名");
            row1.createCell(1).setCellValue("月龄");
            row1.createCell(2).setCellValue("出生年月");
            row1.createCell(3).setCellValue("所在班级");
            row1.createCell(4).setCellValue("托班结束日期");

            row1.getCell(0).setCellStyle(style);
            row1.getCell(1).setCellStyle(style);
            row1.getCell(2).setCellStyle(style);
            row1.getCell(3).setCellStyle(style);
            row1.getCell(4).setCellStyle(style);

        }

        //早教
        if(query.getCategory().intValue() == 2){

            row1.createCell(0).setCellValue("姓名");
            row1.createCell(1).setCellValue("月龄");
            row1.createCell(2).setCellValue("出生年月");
            row1.createCell(3).setCellValue("所在班级");
            row1.createCell(4).setCellValue("总课时");
            row1.createCell(5).setCellValue("剩余课时");
            row1.createCell(6).setCellValue("已排课时");

            row1.getCell(0).setCellStyle(style);
            row1.getCell(1).setCellStyle(style);
            row1.getCell(2).setCellStyle(style);
            row1.getCell(3).setCellStyle(style);
            row1.getCell(4).setCellStyle(style);
            row1.getCell(5).setCellStyle(style);
            row1.getCell(6).setCellStyle(style);
        }
    }


    public static void createRowIndexI( ChildrenQuery query, HSSFWorkbook workbook ,HSSFSheet sheet , List<WebChildrenVo> childrenVoList){

        HSSFCellStyle style = workbook.createCellStyle();
        PoiUtils.setupCellTableStyle(style);

        for (int i = 0 ; i < childrenVoList.size(); i++){
            WebChildrenVo childrenVo = childrenVoList.get(i);

            HSSFRow rowi = sheet.createRow(i + 2);
            rowi.setHeight((short) (2 * 256));
            if(query.getCategory().intValue() == 0){
                String name = childrenVo.getName();
                int month = childrenVo.getMonth();
                String birthday = new DateTime(childrenVo.getBirthday()).toString("yyyy-MM-dd");
                String className = childrenVo.getClssesName();

                rowi.createCell(0).setCellValue(name);
                rowi.createCell(1).setCellValue(month);
                rowi.createCell(2).setCellValue(birthday);
                rowi.createCell(3).setCellValue(className);

                rowi.getCell(0).setCellStyle(style);
                rowi.getCell(1).setCellStyle(style);
                rowi.getCell(2).setCellStyle(style);
                rowi.getCell(3).setCellStyle(style);

            }

            if(query.getCategory().intValue() == 1){

                String name = childrenVo.getName();
                int month = childrenVo.getMonth();
                String birthday = new DateTime(childrenVo.getBirthday()).toString("yyyy-MM-dd");
                String className = childrenVo.getNurseryClassName();
                String nurseryEndDate = new DateTime(childrenVo.getNurseryEndDate()).toString("yyyy-MM-dd");

                rowi.createCell(0).setCellValue(name);
                rowi.createCell(1).setCellValue(month);
                rowi.createCell(2).setCellValue(birthday);
                rowi.createCell(3).setCellValue(className);
                rowi.createCell(4).setCellValue(nurseryEndDate);

                rowi.getCell(0).setCellStyle(style);
                rowi.getCell(1).setCellStyle(style);
                rowi.getCell(2).setCellStyle(style);
                rowi.getCell(3).setCellStyle(style);
                rowi.getCell(4).setCellStyle(style);
            }

            if(query.getCategory().intValue() == 2){
                String name = childrenVo.getName();
                int month = childrenVo.getMonth();
                String birthday = new DateTime(childrenVo.getBirthday()).toString("yyyy-MM-dd");
                String className = childrenVo.getEarlyClassName();

                int earlyTotalCourseNum = childrenVo.getEarlyTotalCourseNum(); //总课时
                int earlyLeftCourseNum = childrenVo.getEarlyLeftCourseNum(); //剩余课时
                int earlyPlanCourseNum = childrenVo.getEarlyPlanCourseNum(); //已排课

                rowi.createCell(0).setCellValue(name);
                rowi.createCell(1).setCellValue(month);
                rowi.createCell(2).setCellValue(birthday);
                rowi.createCell(3).setCellValue(className);
                rowi.createCell(4).setCellValue(earlyTotalCourseNum);
                rowi.createCell(5).setCellValue(earlyLeftCourseNum);
                rowi.createCell(6).setCellValue(earlyPlanCourseNum);

                rowi.getCell(0).setCellStyle(style);
                rowi.getCell(1).setCellStyle(style);
                rowi.getCell(2).setCellStyle(style);
                rowi.getCell(3).setCellStyle(style);
                rowi.getCell(4).setCellStyle(style);
                rowi.getCell(5).setCellStyle(style);
                rowi.getCell(6).setCellStyle(style);
            }
        }
    }

}
